﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Globalization;

using HostsManager.Controls;
using HostsManager.Model;
using HostsManager.Services;

namespace HostsManager.Forms
{
    // Este comentario solo está en el branch 01
    public partial class Form1 : Form
    {
        internal delegate void ExitApplicationEventHandler(object sender);
        internal event ExitApplicationEventHandler ExitApplication;

        internal Hosts Hosts
        {
            get { return hosts; }
            set { 
                hosts = value;
                RefreshForm();
            }
        }
        private Hosts hosts = null;

        internal string CurrentFilePath
        {
            get { return currentFilePath; }
            set { 
                currentFilePath = value;
                txtCurrentFilePath.Text = currentFilePath;
                statusStrip1.Refresh();
            }
        }
        private string currentFilePath = string.Empty;

        public Form1()
        {
            InitializeComponent();
            
            try 
	        {
                // Try to load hosts file from  windows\system32\drivers\etc (may fail because privileges)
                CurrentFilePath = Path.Combine(Path.Combine(Environment.SystemDirectory, @"drivers\etc"), "hosts");
                this.Hosts = HostsService.LoadHostsFromFile(CurrentFilePath);
	        }
	        catch (Exception) {}

            this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
            this.tree1.DataChanged += new TreeControl.DataChangedEventHandler(OnDataChanged);
            this.tree1.NewSection += new TreeControl.NewSectionEventHandler(OnNewSection);
            this.tree1.RenameSection += new TreeControl.RenameSectionEventHandler(OnRenameSection);
            this.tree1.RemoveSection += new TreeControl.RemoveSectionEventHandler(OnRemoveSection);
            this.tree1.AddConfiguration += new TreeControl.AddConfigurationEventHandler(OnAddConfiguration);
            this.tree1.EditConfiguration += new TreeControl.EditConfigurationEventHandler(OnEditConfiguration);
            this.tree1.RenameConfiguration += new TreeControl.RenameConfigurationEventHandler(OnRenameConfiguration);
            this.tree1.RemoveConfiguration += new TreeControl.RemoveConfigurationEventHandler(OnRemoveConfiguration);
            
        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Hide();
            e.Cancel = true;
        }

        protected void OnNewSection(object sender)
        {
            Section section = new Section(hosts.GetUnusedSectionName(), true);
            Configuration configuration = new Configuration(section.GetUnusedConfigurationName(), true);

            section.AddConfiguration(configuration);
            hosts.AddSection(section);

            RefreshForm();
        }

        void OnRenameSection(Section section)
        {
            string name = section.Name;
            string originalName = section.Name;

            if (InputBox.Show(strings.EnterNewNameForSection, strings.RenameSection, ref name)== System.Windows.Forms.DialogResult.OK)
            {
                if ((name==originalName) || !hosts.Sections.Keys.Contains(name))
                {
                    if (name != originalName)
                    {
                        hosts.RemoveSection(section);
                        section.Name = name;
                        hosts.AddSection(section);

                        RefreshForm();
                    }
                }
                else
                {
                    MessageBox.Show(strings.SectionNameMustBeUnique, strings.RenameSection, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        void OnRemoveSection(Section section)
        {
            if (MessageBox.Show(string.Format(strings.DeleteSectionConfirmation, section.Name), strings.DeleteSectionConfirmationTitle, MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.OK)
            {
                hosts.RemoveSection(section);
                RefreshForm();
            }
        }

        void OnAddConfiguration(Section section)
        {
            Configuration configuration = new Configuration(section.GetUnusedConfigurationName(), false);
            section.AddConfiguration(configuration);
            RefreshForm();
        }

        protected void OnEditConfiguration(Configuration configuration)
        {
            string value = configuration.Content;
            string title = configuration.ParentSection.Name + "\\" + configuration.Name;

            if (EditConfiguration.Edit(title, ref value) == System.Windows.Forms.DialogResult.OK)
            {
                configuration.Content = value;
                RefreshForm();
            }
        }

        protected void OnRenameConfiguration(Configuration configuration)
        {
            string name = configuration.Name;
            string originalName = configuration.Name;
            Section section = configuration.ParentSection;

            if (InputBox.Show(strings.EnterNewNameForConfiguration, strings.RenameConfiguration, ref name) == System.Windows.Forms.DialogResult.OK)
            {
                if ((name == originalName) || section.GetConfiguration(name) == null)
                {
                    if (name != originalName)
                    {
                        section.RemoveConfiguration(configuration);
                        configuration.Name = name;
                        section.AddConfiguration(configuration);

                        RefreshForm();
                    }
                }
                else
                {
                    MessageBox.Show(strings.ConfigurationNameMustBeUnique, strings.RenameSection, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        
        protected void OnRemoveConfiguration(Configuration configuration)
        {
            if (configuration.ParentSection.Configurations.Count() > 1)
            {

                string configId = configuration.ParentSection.Name + "\\" + configuration.Name;
                if (MessageBox.Show(string.Format(strings.DeleteConfigurationConfirmation, configId), strings.DeleteConfigurationConfirmationTitle, MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == System.Windows.Forms.DialogResult.OK)
                {
                    configuration.ParentSection.RemoveConfiguration(configuration);
                    RefreshForm();
                }
            }
            else 
            {
                MessageBox.Show(strings.MustHaveOneConfiguration, strings.DeleteConfigurationConfirmationTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        protected void OnDataChanged(object sender)
        {
            preview1.ShowHosts(Hosts);
        }

        protected void OnApplicationExit(object sender)
        {
            if (ExitApplication != null)
                ExitApplication(sender);
        }

        private void RefreshForm()
        {
            tree1.ShowHosts(Hosts);
            preview1.ShowHosts(Hosts);
        }

        private void SaveAs(Hosts hosts)
        {
            SaveFileDialog dialog = new SaveFileDialog();

            dialog.CreatePrompt = true;
            dialog.DefaultExt = string.Empty;
            dialog.Filter = strings.HostsFileFilter;
            dialog.OverwritePrompt = true;
            dialog.Title = strings.SaveFile;

            switch (dialog.ShowDialog(this))
            {
                case System.Windows.Forms.DialogResult.OK:
                    CurrentFilePath = dialog.FileName;
                    HostsService.SaveHostsToFile(hosts, CurrentFilePath);
                    break;
            }
        }

        private void openMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();

            dialog.CheckFileExists = true;
            dialog.CheckPathExists = true;
            dialog.DefaultExt = string.Empty;
            dialog.Filter = strings.HostsFileFilter;
            dialog.Multiselect = false;
            dialog.Title = strings.LoadFile;

            switch (dialog.ShowDialog(this))
            {
                case System.Windows.Forms.DialogResult.OK:
                    try
                    {
                        Hosts = HostsService.LoadHostsFromFile(dialog.FileName);
                        CurrentFilePath = dialog.FileName;

                        if (Hosts == null)
                            MessageBox.Show(strings.ErrorLoading, strings.LoadFile);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(strings.ErrorLoading + Environment.NewLine + ex.Message, strings.LoadFile);
                    }
                    break;

                default:
                    break;
            }
        }

        private void saveMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                HostsService.SaveHostsToFile(Hosts, CurrentFilePath);
                MessageBox.Show(strings.SuccessfullySaved, strings.SaveFile);
            }
            catch (Exception ex)
            {
                MessageBox.Show(strings.ErrorSaving + Environment.NewLine + ex.Message, strings.SaveFile);
            }
        }

        private void saveAsMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                this.SaveAs(Hosts);
                MessageBox.Show(strings.SuccessfullySaved, strings.SaveFile);
            }
            catch (Exception ex)
            {
                MessageBox.Show(strings.ErrorSaving + Environment.NewLine + ex.Message, strings.SaveFile);
            }
        }

        private void exitMenuItem_Click(object sender, EventArgs e)
        {
            OnApplicationExit(sender);
        }
    }
}
